﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows.Data;
using Microsoft.Practices.ObjectBuilder2;
using TciNewsReader_2014_04.Infrastructure;
using TciNewsReader_2014_04.Interfaces;
using TciNewsReader_2014_04.Model;
using TciNewsReader_2014_04.VmHelpers;
namespace TciNewsReader_2014_04
{
    public sealed partial class ViewModel : INotifyPropertyChanged, IViewModel
    {
        private readonly IConfig _configInitializer;
        public ViewModel(
            IPersistenceManager persistenceManager,
            IConfirmations confirmations,
            IExceptionHandler exceptionHandler,
            IIncludeExclude includeExcludeInitializer,
            IHelpAbout helpAboutInitializer,
            IErrorReport errorReportInitializer,
            IFeedCrud feedCrudInitializer,
            IConfig configInitializer,
            TaskRunner taskRunner)
        {
            _configInitializer = configInitializer;
            VmStats = new Stats();
            _persistenceManager = persistenceManager;
            _confirmations = confirmations;
            _exceptionHandler = exceptionHandler;
            _includeExcludeInitializer = includeExcludeInitializer;
            _helpAboutInitializer = helpAboutInitializer;
            _errorReportInitializer = errorReportInitializer;
            _feedCrudInitializer = feedCrudInitializer;
            _taskRunner = taskRunner;
            FeedInfos = new ObservableCollection<FeedInfo>(); 
            ItemWrappers = new ObservableCollection<ItemWrapper>();
            _itemWrappersListCollectionView = CollectionViewSource.GetDefaultView(ItemWrappers) as ListCollectionView;
            _feedInfosListCollectionView = CollectionViewSource.GetDefaultView(FeedInfos) as ListCollectionView;
            if (_itemWrappersListCollectionView != null && _feedInfosListCollectionView!=null)
            {
                _itemWrappersListCollectionView.IsLiveFiltering = true;
                _itemWrappersListCollectionView.IsLiveSorting = true;
                _itemWrappersListCollectionView.LiveFilteringProperties.Add("FilterStatus");
                InitialiseExceptions();
                InitialiseSorts();
                InitialiseAgeFilter();
                InitialiseFeedCruds();
                _itemWrappersListCollectionView.Filter = ItemFilterDelegate;
            }
            RefreshAllFeeds();
        }
        private void RefreshAllFeeds()
        {
            IsBusy = true;
            IsReadyForInteraction = false;
            MasterViewSelectedItem = null;
            CurrentItemContent = String.Empty;
            CurrentItemTitle = String.Empty;
            CountsStatus = String.Empty;
            VmStats.Clear();
            ItemWrappers.Clear();
            ExceptionInfos.Clear();
            if (!_persistenceManager.FileExists())
            {
                _confirmations.Inform(String.Format("Cannot find {0}.  Please reinstall the program.", Constants.UrlFileLocation));
            }
            _taskRunner.Run(() => _persistenceManager.GetUrlList(BuildFeedInfos));
        }
        private void BuildFeedInfos(List<string> urls)
        {
            if (urls != null)
            {
                foreach (string url in urls)
                {
                    FeedInfo feedInfo = FeedInfos.FirstOrDefault(q => q.Url == url);
                    if (feedInfo == null)
                    {
                        feedInfo = new FeedInfo(url);
                        _feedInfosListCollectionView.Dispatcher.Invoke(() => FeedInfos.Add(feedInfo));
                    }
                    feedInfo.WrappersHaveBeenProcessed = false;
                    ++VmStats.NumberOfFeeds; 
                    _taskRunner.Run(() => feedInfo.Load(_exceptionHandler, ProcessItemWrappers));
                }
            }
        }
        private void ProcessItemWrappers(FeedInfo feedInfo)
        {
            AddExceptions(feedInfo);
            var mre = new ManualResetEvent(false);
            if (_itemWrappersListCollectionView == null) return;
            try
            {
                if (feedInfo.Items.Count > 0)
                {
                    for (int i = 0; i < feedInfo.Items.Count; i++)
                    {
                        _itemWrappersListCollectionView.Dispatcher.Invoke(() =>
                        {
                            lock (Locker)
                            {
                                FilteringHandler(feedInfo.Items[i]);
                                ItemWrappers.Add(feedInfo.Items[i]);
                                if (i == feedInfo.Items.Count - 1)
                                {
                                    _itemWrappersListCollectionView.CommitNew();
                                    VmStats.TotalNumberOfItems += feedInfo.Items.Count;
                                    mre.Set();
                                }
                            }
                        });
                    }
                    mre.WaitOne();
                }
            }
            catch (Exception ex)
            {
                _exceptionHandler.HandleException(ex, "Item processor");
            }
            IsBusy = false;
            feedInfo.WrappersHaveBeenProcessed = true;
            if(FeedInfos.All(q=>q.WrappersHaveBeenProcessed))
            {
                _itemWrappersListCollectionView.Dispatcher.Invoke(() =>
                {
                    FeedInfos.ForEach(q => q.RaiseNotifyOnCounts());
                    _itemWrappersListCollectionView.Refresh();
                    UpdateCountsStatus();
                    _itemWrappersListCollectionView.MoveCurrentToFirst();
                    if (Properties.Settings.Default.NoiseAlerts)
                    {
                        Console.Beep();
                    }
                    IsReadyForInteraction = true;
                });
            }
        }
        private void UpdateCountsStatus()
        {
            lock (Locker)
            {
                if (ItemWrappers == null || FeedInfos == null) return;
                VmStats.NumberOfFilteredItems = ItemWrappers.Count(q => q.FilterStatus == FilterStatus.FilteredIn);
                VmStats.NumberOfIncludedFeeds = FeedInfos.Count(q => q.IncludeInView);
                VmStats.NumberOfSeenItems = ItemWrappers.Count(q => q.ItemStatus == ItemStatus.Read);
                VmStats.NumberOfHistoryItems = ItemWrapperHistoryManager.HistoryCount;
            }
            CountsStatus = VmStats.ToString();
            OnPropertyChanged("CountsStatus");
        }
        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = Interlocked.CompareExchange(ref PropertyChanged, null, null);
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
    }
}